using Microsoft.EntityFrameworkCore;
using StudentVideo.Common.Constants;
using StudentVideo.Common.Exceptions;
using StudentVideo.Common.Models;
using StudentVideo.Data;
using StudentVideo.Data.Entities;
using StudentVideo.Helper;
using StudentVideo.Shared.Dtos.User;
using StudentVideo.Utils;
using System.Linq.Dynamic.Core;
using System.Threading.Tasks;

namespace StudentVideo.Services;

// TODO 用户接口 - 任命、编辑、删除、

public class UserService(AppDbContext context, RedisDbHelper redisDb) {
   private readonly AppDbContext _context = context;
   private readonly RedisDbHelper _redisDb = redisDb;

   /// <summary>
   /// 新增
   /// </summary>
   /// <param name="data"></param>
   /// <returns></returns>
   /// <exception cref="HttpException"></exception>
   public async Task Create(UserCreateRequest data) {
      var username = data.Username;
      var exist = await _context.Users.AnyAsync(u => u.Username == username);
      if (exist)
         throw new HttpException(HttpErrorMessage.USER_EXISTS);

      var salt = PasswordHasher.GenerateSalt();
      var pwd = PasswordHasher.HashPassword(data.Password, salt);
      var newUser = new UserEntity {
         Username = username,
         Nickname = username,
         Password = pwd,
         Salt = salt
      };

      _context.Users.Add(newUser);
      await _context.SaveChangesAsync();

      return;
   }

   /// <summary>
   /// 任命
   /// </summary>
   /// <returns></returns>
   public async Task Appoint(UserAppointRequest data) {
      // 查询用户
      var user = await _context.Users.FirstOrDefaultAsync(e => e.Id == data.UserId)
         ?? throw new HttpException(HttpErrorMessage.USER_NOT_EXIST);

      // 查询角色是否存在
      var roles = await _context.Roles.Where(e => data.RoleIds.Contains(e.Id)).ToListAsync();

      if (roles.Count != data.RoleIds.Count)
         throw new HttpException(HttpErrorMessage.ROLE_INFO_ERROR);

      // 剔除已经任命的角色
      var appointed = await _context.UserRoleMaps.Where(e => e.UserId == data.UserId && data.RoleIds.Contains(e.RoleId)).ToListAsync();
      List<string> appointedIds = [.. appointed.Select(e => e.RoleId)];

      foreach (var id in appointedIds) {
         _context.UserRoleMaps.Add(new() {
            User = user,
            UserId = data.UserId,
            RoleId = id,
            Role = roles.First(e => e.Id == id)
         });
      }

      await _context.SaveChangesAsync();
   }

   // TODO 取消任命


   // TODO 用户编辑

}
